Skip to content

Improvement: IBFlex stricter security matching#5303

Draft
georgemac-labs wants to merge 3 commits intoportfolio-performance:masterfrom
georgemac-labs:ibflex-improved-security-matching
Draft

Improvement: IBFlex stricter security matching#5303
georgemac-labs wants to merge 3 commits intoportfolio-performance:masterfrom
georgemac-labs:ibflex-improved-security-matching

Conversation

@georgemac-labs
Copy link
Contributor

@georgemac-labs georgemac-labs commented Jan 4, 2026

Note: depends on #5292

When importing from IBKR, I have had some issues with transactions being matched to the wrong securities.

The importer currently starts with CONID, which is good, as it’s closest to universal and unambiguous. However, if that fails, it falls back to ISIN, and then symbol, which are ambiguous identifiers. The following scenarios are considered a match:

  • Same ISIN, even if there’s a currency mismatch (this looks like a different trading line of the security e.g. EQQQ.F vs EQQQ.L)
  • Same symbol, even if there’s an ISIN mismatch (this looks like a completely different instrument!)
  • Same symbol, even if there’s a currency mismatch (could be either of the above)

This PR tightens the rules as follows:

  • If an ISIN is stored for a security, it must match the import transaction. If it doesn’t, it’s not a match, and a new security should be created.
  • If the transaction is a trade, currency must match the stored security. If it doesn’t, it’s not a match, and a new security should be created. Caveat: this rule does not apply for dividends, as those are not always paid in the listing currency.
  • The currency checks build on previous PRs1 and recognise that the currency does match even if there is a mix of major and minor units (important because e.g. IB Flex reports can use GBP values for GBX listed securities)

Note: I amended the existing unit test, because it contained a trade and a dividend payment where the symbols matched but the CONIDs did not. I traced the origin of the test data and it seems the dividend payment is copied from a different security: #812 (comment), so it doesn't tell us anything about real IBKR data. I only have my personal data to go on, but it's almost 9000 records, and I have zero cases where a CashTransaction has a different CONID from the associated Trade. Thus: I'm working with the assumption that they should always match.

These rules make sense to me, but I may have overlooked some facts and – as always – I’m happy to hear feedback.

Closes: #4700

Footnotes

  1. Improvement: IBFlex handle currency unit mismatches #5291
    Improvement: IBFlex support cross-currency dividend import #5292

Extend IBFlex importer to handle cases where the reported unit is not the same as the unit the exchange quotes in (e.g. GBP vs GBX)
When dividend currency differs from security currency and no direct
conversion rate exists, use fxRateToBase from the CashTransaction
element to calculate cross-rates via the account's base currency.
Also handles minor unit securities (e.g., USD→GBX via EUR→GBP→GBX).
@georgemac-labs georgemac-labs marked this pull request as draft January 4, 2026 22:42
@georgemac-labs georgemac-labs force-pushed the ibflex-improved-security-matching branch from c3cd843 to b2d0efb Compare January 5, 2026 01:49
- If existing security has an ISIN, it must match
- Currency must match the existing security (trades only)
- Currency matching supports major/minor units
@georgemac-labs georgemac-labs force-pushed the ibflex-improved-security-matching branch from b2d0efb to 6d6294c Compare January 5, 2026 02:36
@georgemac-labs georgemac-labs marked this pull request as ready for review January 5, 2026 11:03
Copy link
Member

@buchen buchen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's wait for the other pull request to conclude - this one is independent but sits on top of the other pull request.

The checks wether CONID or ISIN conflict if the ticker is present make sense to me.

Comment on lines +1225 to +1226
* @param strictCurrencyMatch If true (for trades), only match on ISIN if currency also matches.
* If false (for dividends), allow ISIN match regardless of currency.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the rationale between separating the instrument matching whether it is a trade (purchase, sale) or a dividend transactions?

Wouldn't we get mismatches? Say a purchase creates a new security (strict match) but the corresponding dividend than is matched to the previous instrument (because it is not strictly matching).

Copy link
Contributor Author

@georgemac-labs georgemac-labs Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trades are treated differently because the currency should always match. If it doesn't, you can be sure that should be a different security in PP.

With dividends, you don't know, because they are sometimes not paid in the listing currency. Currency mismatch is not evidence for creating a security.

And yes, you can have a mismatch. Real-world example: you have EQQQ.F (EUR) and EQQQ.L (GBP) and both pay a dividend in USD. You don't have the CONIDs stored in the WKD field. Both have the same ISIN. Currency doesn't match, but that proves nothing. Where do you assign the dividend? Currently impossible to say.

You could try to solve this using the CashTransaction's listingExchange attribute, but I think that would be more complexity, a pain to maintain (mapping table with exchange codes) and still imperfect – and all that for an edge-case.

I ignored this case, because it's not easy to get into this situation. You need to:

  • Own the same instrument in multiple currencies AND
  • Receive a third-currency dividend AND
  • Not have the CONIDs saved

... although the joke is – that's exactly what happened to me.

Really, if you're doing non-trivial stuff with IBKR, you want CONIDs saved for all securities. And I think the IBFlex importer is getting more powerful and accurate, so in the future that should be the norm. I only ended up with securities without CONIDs due to importer issues.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair. I am wondering if the user will understand the subtle difference between matching trades and dividends. I would think it is easier if it is one algorithm - and if it mixes it up, fix the meta data once and for all.

And if a new instrument is created, the user could still choose to apply them to an existing instrument:

Bildschirmfoto 2026-01-05 um 20 22 00


if (!isin.isEmpty() && isin.equals(security.getIsin()))
if (currency.equals(security.getCurrencyCode()))
if (isCurrencyCompatible(currency, security.getCurrencyCode()))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that point (and I understand this has nothing to do with the strict mode). I am just wondering if we take the use of the FixedEchangeRateProvider a little to far. The user could still have a DEM instrument, but I am not sure if he wants to use that instead of the creating a new EUR instrument. Maybe GBX and GBP is a special case because apparently it used interchangeably.

Copy link
Contributor Author

@georgemac-labs georgemac-labs Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will need to look at this, but I'd say the data modelling is fundamentally a bit off. GBP and GBX are not two currencies – they are two units of the same, like Euros and Euro cents. Their relationship is quite different from DEM and EUR. But I didn't even consider opening that can of worms!

@buchen buchen added pdf blocked Blocked due to external dependencies labels Jan 5, 2026
@georgemac-labs georgemac-labs marked this pull request as draft January 5, 2026 22:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Blocked due to external dependencies pdf

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Import IBKR, multiple currencies, the same security

2 participants